package root.electronclass.electronclass.grade.widget

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import root.electronclass.electronclass.R
import java.text.DecimalFormat
import kotlin.random.Random

/**
 * 图表
 * @author Lokiy
 * @date 2023/3/25 16:23
 */
open class LineChartView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    View(context, attrs, defStyleAttr) {
    private val mPaint = Paint()
    private val mLinePaint = Paint()

    val data: MutableList<LineChartData> = mutableListOf()
    private val path = Path()

    //横着的有多少条线 不包含X轴
    var horizontalLineCount = 7
    private var verticalSpace = 0f
    private var horizontalSpace = 0f
    private val df = DecimalFormat("0.#")
    var yFormatter: (index: Int) -> String = { it.toString() }

    private var isDrawPoint = false

    init {
        var lineWidth = 0f
        context.obtainStyledAttributes(attrs, R.styleable.LineChartView).also {
            horizontalLineCount = it.getInt(R.styleable.LineChartView_horizontalLineCount, horizontalLineCount)
            isDrawPoint = it.getBoolean(R.styleable.LineChartView_isDrawPoint, isDrawPoint)
            verticalSpace = it.getDimension(R.styleable.LineChartView_verticalSpace, dp2px(30f))
            horizontalSpace = it.getDimension(R.styleable.LineChartView_horizontalSpace, dp2px(30f))
            lineWidth = it.getDimension(R.styleable.LineChartView_lineWidth, dp2px(2f))
        }.recycle()
        mPaint.color = 0xFF000000.toInt()
        mPaint.strokeWidth = dp2px(1f)
        mPaint.textSize = dp2px(12f)
        mPaint.style = Paint.Style.FILL
        mPaint.isAntiAlias = true

        //折线画笔
        mLinePaint.strokeWidth = lineWidth
        mLinePaint.style = Paint.Style.STROKE
        mLinePaint.isAntiAlias = true
        if (isInEditMode) {
            repeat(2) {
                val line = mutableListOf<Float>()
                repeat(7) {
                    line.add(Random.nextInt(20) + 20f)
//                    line.add((it + 1) * 10f)
                }
                val item = LineChartData(Color.rgb(Random.nextInt(255), Random.nextInt(255), Random.nextInt(255)), line)
                data += item
            }
        }
    }

    override fun onDraw(canvas: Canvas) {
        if (data.isEmpty()) return

        val chartWidth = width.toFloat() - horizontalSpace * 2 //图表宽度
        val chartHeight = height.toFloat() - verticalSpace * 2 //图表高度

        var maxCount = data.maxOfOrNull { it.values.maxOrNull() ?: 0f } ?: 0f
        maxCount = if (maxCount == 0f) {
            30f
        } else {
            maxCount.toInt() / 10 * 10 + 10f
        }
        val maxSize = data.maxOf { it.values.size }
        val itemWidth = chartWidth / maxSize
        val itemHeight = chartHeight / horizontalLineCount

        //绘制X轴的值
        mPaint.alpha = (0.15f * 255).toInt()
        for (index in 0..horizontalLineCount) {
            val y = index * itemHeight + verticalSpace
            val value = (horizontalLineCount - index) * maxCount / horizontalLineCount
            mPaint.alpha = if (index == horizontalLineCount) (0.25f * 255).toInt() else (0.15f * 255).toInt()
            canvas.drawLine(horizontalSpace, y, width - horizontalSpace, y, mPaint) //X轴
            val text = df.format(value)
            mPaint.alpha = (0.45f * 255).toInt()
            canvas.drawText(text, horizontalSpace - mPaint.measureText(text) - dp2px(5f), y + mPaint.textSize / 3, mPaint) //X
        }
        //绘制Y轴的值
        val lineY = horizontalLineCount * itemHeight + verticalSpace
        val textY = lineY + dp2px(10f) + mPaint.textSize
        for (index in 0 until maxSize) {
            val x = itemWidth * index + itemWidth / 2 + horizontalSpace
            val text = yFormatter.invoke(index)
            mPaint.alpha = (0.45f * 255).toInt()
            canvas.drawText(text, x - mPaint.measureText(text) / 2, textY, mPaint) //X
            mPaint.alpha = (0.25f * 255).toInt()
            canvas.drawLine(x, lineY, x, lineY + dp2px(5f), mPaint)//Y
        }
        //绘制折线区
        data.forEach {
            path.reset()
            mLinePaint.color = it.color
            it.values.forEachIndexed { index, num ->
                val y = chartHeight * (1 - num / maxCount) + verticalSpace
                val x = itemWidth * index + itemWidth / 2 + horizontalSpace
                if (index == 0) {
                    path.moveTo(x, y)
                } else {
                    path.lineTo(x, y)
                }
                if (isDrawPoint) {
                    mLinePaint.style = Paint.Style.FILL
                    canvas.drawCircle(x, y, mLinePaint.strokeWidth * 1.5f, mLinePaint)
                }
            }
            mLinePaint.style = Paint.Style.STROKE
            canvas.drawPath(path, mLinePaint) //折线
        }
    }

    private fun dp2px(value: Float) = value

    data class LineChartData(
        val color: Int,
        val values: List<Float>,
    )


}